package lession7.PartA_Grammar.asyn_cancel

import kotlinx.coroutines.*

var acquired = 0

class Resource {
    init {
        acquired++
    } // Acquire the resource

    fun close() {
        acquired--.also { println("Resource acquired = $acquired") }
    } // Release the resource
}

fun main() {
    testWithTimeOut3()
}

fun testWithTimeOut1() = runBlocking {
    launch {
        println("${System.currentTimeMillis()} launch1 acquired=$acquired")
        try {
            val resource = withTimeout(60) { // Timeout of 60 ms
                println("${System.currentTimeMillis()} withTimeout1 acquired=$acquired")
                delay(50) // Delay for 50 ms
                println("${System.currentTimeMillis()} withTimeout2 acquired=$acquired")
                Resource().also {
                    println("${System.currentTimeMillis()} withTimeout3 acquired=$acquired")
                }// Acquire a resource and return it from withTimeout block
            }
            println("${System.currentTimeMillis()}  launch2  acquired = $acquired")
            resource.close() // Release the resource
        } catch (e: CancellationException) {
            println("${System.currentTimeMillis()} catch ${e.message} acquired=$acquired")
        }
    }
    println("${System.currentTimeMillis()} testWithTimeOut1 acquired=$acquired")
}

fun testWithTimeOut2() = runBlocking {
    println("${System.currentTimeMillis()} repeat acquired=$acquired")
    repeat(10) { // Launch 100K coroutines
        launch {
            println("${System.currentTimeMillis()} launch1 it =$it acquired=$acquired")
            try {
                val resource = withTimeout(60) { // Timeout of 60 ms
                    println("${System.currentTimeMillis()} withTimeout1 it =$it acquired=$acquired")
                    delay(50) // Delay for 50 ms
                    println("${System.currentTimeMillis()} withTimeout2 it =$it acquired=$acquired")
                    Resource().also {
                        println("${System.currentTimeMillis()} withTimeout3 it =$it acquired=$acquired")
                    }// Acquire a resource and return it from withTimeout block

                }
                println("launch2 it =$it acquired = $acquired")
                resource.close() // Release the resource
            } catch (e: CancellationException) {
                println("${System.currentTimeMillis()} catch ${e.message}")
            }

        }
    }
}

fun testWithTimeOut3() {
    runBlocking {
        repeat(100_00) { // Launch 100K coroutines
            launch {
                var resource: Resource? = null // Not acquired yet
                try {
                    withTimeout(200) { // Timeout of 60 ms
                        delay(50) // Delay for 50 ms
                        resource = Resource() // Store a resource to the variable if acquired
                    }
                    // We can do something else with the resource here
                } catch (e:CancellationException){
                    print("catch it = $it message e=${e.message} resource is null =${resource==null} ")
                }finally {
                    resource?.close() // Release the resource if it was acquired
                }
            }
        }
    }
    // Outside of runBlocking all coroutines have completed
    println(acquired) // Print the number of resources still acquired
}